package zero.tech.games.logic.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.util.Assert;

import zero.tech.core.ZeroContext;
import zero.tech.core.data.Resp;
import zero.tech.core.data.SimpleUser;
import zero.tech.core.event.service.api.EventService;
import zero.tech.core.util.RandomUtil;
import zero.tech.def.DefFactory;
import zero.tech.games.common.Code;
import zero.tech.games.common.ConfigServerConsts;
import zero.tech.games.common.PipeiGroup;
import zero.tech.games.common.RoomIdUtil;
import zero.tech.games.common.RoomNodeUtil;
import zero.tech.games.common.UserLastRoomUtil;
import zero.tech.games.common.data.RoomNode;
import zero.tech.games.def.xml.ConfigLogicServer;
import zero.tech.games.def.xml.ConfigType;
import zero.tech.games.entity.games.Club;
import zero.tech.games.logic.common.CacheRoom;
import zero.tech.games.logic.common.GameBase;
import zero.tech.games.logic.common.Room;
import zero.tech.games.logic.common.RoomCache;
import zero.tech.games.logic.common.RoomType;
import zero.tech.games.logic.data.DissolutionData;
import zero.tech.games.logic.data.LogicEventType;
import zero.tech.games.logic.data.consts.LOGICCMD;
import zero.tech.games.logic.service.api.ILogicService;
import zero.tech.wsnet.controller.CacheOnline;
import zero.tech.wsnet.controller.LogicController;
import zero.tech.wsnet.data.Message;
import zero.tech.wsnet.net.CacheClient;
import zero.tech.wsnet.net.WebClient;

public class LogicUtil {
	
	public static Resp joinRoom(Room room, SimpleUser simpleUser) {
		int room_type=room.getRoom_type();
		if(room_type== RoomType.PIPEI_ROOM&&!room.getAllControllers().containsKey(simpleUser.getUid())) {
			//匹配房间,不允许直接加入
			return Resp.build(Code.CANT_JOIN_PIPEI_ROOM, "该房间属于防作弊房间,不能直接加入");
		}
		EventService eventService=ZeroContext.getInstance(EventService.class);
		Club club=room.getClub();
		if(club==null) {
			Boolean check_join_nomal_room_needmoney=null;
			//加入普通房间检查条件
			check_join_nomal_room_needmoney=eventService.engineCallBack(LogicEventType.CHECK_JOIN_NOMAL_ROOM_NEEDMONEY, room,simpleUser);
			if(check_join_nomal_room_needmoney==null||check_join_nomal_room_needmoney) {
				ILogicService logicService=ZeroContext.getInstance(ILogicService.class);
				return logicService.roomJoined(room,simpleUser);
			}else {
				return Resp.build(Code.DIAMOND_NOT_ENOUGH, "砖石不足");
			}
		}else {
			Boolean check_join_club_room_needmoney=null;
			//加入俱乐部房间检查条件
			check_join_club_room_needmoney=eventService.engineCallBack(LogicEventType.CHECK_JOIN_CLUB_ROOM_NEEDMONEY, room,simpleUser);
			if(check_join_club_room_needmoney!=null&&check_join_club_room_needmoney) {
				ILogicService logicService=ZeroContext.getInstance(ILogicService.class);
				return logicService.roomJoined(room,simpleUser);
			}else {
				return Resp.build(Code.MONEY_NOT_ENOUGH, "入场费不够");
			}
		}
	}

	
	public static Resp createPipeiRoom(List<PipeiGroup> pipeiGroups, String configStr, String host, String port, String service_id, Integer game_id,
			Club club) {
		Map<String,RoomNode> map=new HashMap<>();
		EventService eventService=ZeroContext.getInstance(EventService.class);
		for(PipeiGroup pipeiGroup:pipeiGroups) {
			String room_id=randRoomId();
			long queue_id=randNomalQueueId();
			Room room=new Room(host,port,service_id,configStr, room_id, queue_id,game_id,club, RoomType.PIPEI_ROOM);
			CacheRoom.getCache().getRooms().put(room.getRoom_id(), room);
			eventService.engineNotify(LogicEventType.ROOM_CREATED, room);
			pipeiRoomCreated(room, pipeiGroup);
			map.put(pipeiGroup.getId(), room.getRoomNode());
		}
		return Resp.build(Code.OK, "匹配房间创建成功",map);
	}
	
	
	private static void pipeiRoomCreated(Room room, PipeiGroup pipeiGroup) {
		EventService eventService=ZeroContext.getInstance(EventService.class);
		Map<Integer,SimpleUser> map=pipeiGroup.getSimpleUsers();
		for(Entry<Integer,SimpleUser> entry:map.entrySet()){
			SimpleUser simpleUser=entry.getValue();
			Boolean check_join_club_room_needmoney=null;
			//加入俱乐部房间检查条件
			check_join_club_room_needmoney=eventService.engineCallBack(LogicEventType.CHECK_JOIN_CLUB_ROOM_NEEDMONEY, room,simpleUser);
			if(check_join_club_room_needmoney!=null&&check_join_club_room_needmoney) {
				ILogicService logicService=ZeroContext.getInstance(ILogicService.class);
				Resp resp=logicService.roomJoined(room,simpleUser);
				if(Code.OK.equals(resp.getCode())) {
					//自动准备
					LogicController logicController=room.getAllControllers().get(simpleUser.getUid());
					logicService.reqReady(room, logicController);
				}
			}
		}		
	}


	public static Resp quickJoinClubRoom(SimpleUser simpleUser, String configStr, String host, String port,
			String service_id, Integer game_id, Club club, String pipei_key) {
		//首先找pipei_key相同的房间进行加入,没有则创建房间
		Map<String,Room> rooms=CacheRoom.getCache().getRooms();
		List<Room> match=new ArrayList<>();
		for(Room room:rooms.values()) {
			if(room.getAllControllers().size()<room.getMax_player()
					&&room.getRoom_type()==RoomType.NOMAL_ROOM
					&&room.getRoomNode().getPipei_key().equals(pipei_key)
					&&room.getClub()!=null
					&&room.getClub().getClub_id().intValue()==club.getClub_id().intValue()) {
				match.add(room);
			}
		}
		Room find=null;
		if(!match.isEmpty()) {
			Collections.shuffle(match);
			find=match.get(0);
		}
		EventService eventService=ZeroContext.getInstance(EventService.class);
		if(find==null) {
			String room_id=randRoomId();
			long queue_id=randNomalQueueId();
			//创建房间
			Boolean check_create_club_room_needmoney=null;
			//创建俱乐部房间检查条件
			check_create_club_room_needmoney=eventService.engineCallBack(LogicEventType.CHECK_CREATE_CLUB_ROOM_NEEDMONEY, simpleUser,configStr,club);
			if(check_create_club_room_needmoney!=null&&check_create_club_room_needmoney) {
				find=new Room(host,port,service_id,configStr, room_id, queue_id,game_id,club, RoomType.NOMAL_ROOM);
				CacheRoom.getCache().getRooms().put(find.getRoom_id(), find);
				eventService.engineNotify(LogicEventType.ROOM_CREATED, find);
				ILogicService logicService=ZeroContext.getInstance(ILogicService.class);
				return logicService.roomCreated(find, simpleUser);
			}else {
				return Resp.build(Code.MONEY_NOT_ENOUGH, "入场费不够");
			}
		}else {
			//加入房间
			Boolean check_join_club_room_needmoney=null;
			//加入俱乐部房间检查条件
			check_join_club_room_needmoney=eventService.engineCallBack(LogicEventType.CHECK_JOIN_CLUB_ROOM_NEEDMONEY, find,simpleUser);
			if(check_join_club_room_needmoney!=null&&check_join_club_room_needmoney) {
				ILogicService logicService=ZeroContext.getInstance(ILogicService.class);
				return logicService.roomJoined(find,simpleUser);
			}else {
				return Resp.build(Code.MONEY_NOT_ENOUGH, "入场费不够");
			}
		}
	}
	
	
	
	public static Resp createRoom(SimpleUser simpleUser,String configStr, String host, String port,
			String service_id, int game_id, Club club) {
		String room_id=randRoomId();
		long queue_id=randNomalQueueId();
		EventService eventService=ZeroContext.getInstance(EventService.class);
		if(club==null) {
			Boolean check_create_nomal_room_needmoney=null;
			//创建普通房间检查条件
			check_create_nomal_room_needmoney=eventService.engineCallBack(LogicEventType.CHECK_CREATE_NOMAL_ROOM_NEEDMONEY, simpleUser,configStr);
			if(check_create_nomal_room_needmoney==null||check_create_nomal_room_needmoney) {
				Room room=new Room(host,port,service_id,configStr, room_id, queue_id,game_id,club, RoomType.NOMAL_ROOM);
				CacheRoom.getCache().getRooms().put(room.getRoom_id(), room);
				eventService.engineNotify(LogicEventType.ROOM_CREATED, room);
				ILogicService logicService=ZeroContext.getInstance(ILogicService.class);
				return logicService.roomCreated(room, simpleUser);
			}else {
				return Resp.build(Code.DIAMOND_NOT_ENOUGH, "砖石不足");
			}
		}else {
			Boolean check_create_club_room_needmoney=null;
			//创建俱乐部房间检查条件
			check_create_club_room_needmoney=eventService.engineCallBack(LogicEventType.CHECK_CREATE_CLUB_ROOM_NEEDMONEY, simpleUser,configStr,club);
			if(check_create_club_room_needmoney!=null&&check_create_club_room_needmoney) {
				Room room=new Room(host,port,service_id,configStr, room_id, queue_id,game_id,club, RoomType.NOMAL_ROOM);
				CacheRoom.getCache().getRooms().put(room.getRoom_id(), room);
				eventService.engineNotify(LogicEventType.ROOM_CREATED, room);
				ILogicService logicService=ZeroContext.getInstance(ILogicService.class);
				return logicService.roomCreated(room, simpleUser);
			}else {
				return Resp.build(Code.MONEY_NOT_ENOUGH, "入场费不够");
			}
		}
	}
	

	private static long randNomalQueueId() {
		int queue_limit=16;
		ConfigLogicServer configLogicServer=DefFactory.getFactory().getDef(ConfigType.CONFIG_LOGIC_SERVER, ConfigServerConsts.DEFAULT_NOMAL_QUEUE_LIMIT);
		if(configLogicServer!=null) {
			String val=configLogicServer.getVal();
			queue_limit=Integer.valueOf(val);
		}
		int queue_id=RandomUtil.randInt(queue_limit+1);
		return queue_id;
	}


	public static String randRoomId() {
		RoomIdUtil roomIdUtil=ZeroContext.getInstance(RoomIdUtil.class);
		return roomIdUtil.randRoomId();
	}


	public static Integer getFreePos(Room room) {
		Integer pos=null;
		Map<Integer,Integer> map=room.getSeats();
		for(Entry<Integer,Integer> entry:map.entrySet()) {
			if(entry.getValue()==null) {
				pos=entry.getKey();
				break;
			}
		}
		return pos;
	}
	
	public static Integer getPosByUid(Room room,int uid) {
		Integer pos=null;
		Map<Integer,Integer> map=room.getSeats();
		for(Entry<Integer,Integer> entry:map.entrySet()) {
			if(entry.getValue()!=null&&uid==entry.getValue()) {
				pos=entry.getKey();
				break;
			}
		}
		return pos;
	}





	public static void freeRoomController(Room room, LogicController logicController,boolean broad, Message... msgs) {
		int uid=logicController.getId();
		if(room.getAllControllers().containsKey(uid)) {
			String room_id=room.getRoom_id();
			LogicController controller=room.getAllControllers().remove(uid);
			Integer pos=getPosByUid(room, uid);
			Assert.notNull(pos,"此处pos不为null");
			room.getSeats().put(pos,null);
			GameBase gameBase = room.getGameBase();
			gameBase.getReadys().remove(uid);
			RoomCache roomCache = room.getRoomCache();
			roomCache.getWatchers().remove(logicController.getId());//从观战者中移除
			roomCache.getTaotais().remove(logicController.getId());
			roomCache.getBirds().remove(controller.getId());//打鸟数据移除
			UserLastRoomUtil userLastRoomUtil=ZeroContext.getInstance(UserLastRoomUtil.class);
			userLastRoomUtil.delete(String.valueOf(uid), room_id);
			if(broad) {
				broadRoomAllControllersInclude(room,Message.build(LOGICCMD.NOTIFY_SOMEONE_LEAVE, Resp.build(Code.OK, "某人离开房间",PckUtil.packageNotifySomeOneLeave(logicController))));
			}
			if(msgs.length>0) {
				for(Message msg:msgs) {
					controller.getWebClient().sendMessage(msg);
				}
			}
			CacheOnline.getCache().offline(controller);
			WebClient  webClient=controller.getWebClient();
			webClient.setController(null);
			controller.setWebClient(null);
			controller=null;
			CacheClient.remove(webClient);
			roomNodeUpdate(room);
		}
	}
	
	
	public static void freeRoom(Room room,Message... msgs) {
		String room_id=room.getRoom_id();
		Collection<LogicController> controllers=room.getAllControllers().values();
		for(LogicController controller:controllers) {
			freeRoomController(room, controller,false, msgs);
		}
		room.getAllControllers().clear();
		RoomNode roomNode=room.getRoomNode();
		CacheRoom.getCache().removeRoom(room);
		System.out.println("房间被释放了");
		RoomNodeUtil roomNodeUtil=ZeroContext.getInstance(RoomNodeUtil.class);
		roomNodeUtil.delete(room_id,roomNode.getClub_id());
	}

	
	public static void clearRoom(int uid, String roomId, String club_no) {
		UserLastRoomUtil userLastRoomUtil = ZeroContext.getInstance(UserLastRoomUtil.class);
		userLastRoomUtil.delete(String.valueOf(uid), roomId);
		RoomNodeUtil roomNodeUtil=ZeroContext.getInstance(RoomNodeUtil.class);
		roomNodeUtil.delete(roomId,club_no);
	}
	
	public static void broadRoomAllControllersInclude(Room room, Message message,LogicController...includes) {
		Map<Integer,LogicController> map = new HashMap<Integer, LogicController>();
		map.putAll(room.getAllControllers());
		if(includes.length>0) {
			for(LogicController include:includes) {
				map.remove(include.getId());
			}
		}
		
		Collection<LogicController> controllers=map.values();
		for(LogicController logicController:controllers) {
			logicController.getWebClient().sendMessage(message);
		}
	}
	
	
	public static void broadRoomControllersWithoutWatcherAndTaotais(Room room, Message message,LogicController...includes) {
		Map<Integer,LogicController> map = new HashMap<Integer, LogicController>();
		map.putAll(room.getControllersWithoutWatcherAndTaotai());
		
		if(includes.length>0) {
			for(LogicController include:includes) {
				map.remove(include.getId());
			}
		}
		
		Collection<LogicController> controllers=map.values();
		for(LogicController logicController:controllers) {
			logicController.getWebClient().sendMessage(message);
		}
	}
	
	
	public static void broadRoomWatcherAndTaotais(Room room, Message message,LogicController...includes) {
		Map<Integer,LogicController> map = new HashMap<Integer, LogicController>();
		Map<Integer,LogicController> watcherAndTaotais=room.getWatcherAndTaotai();
		map.putAll(watcherAndTaotais);
		
		if(includes.length>0) {
			for(LogicController include:includes) {
				map.remove(include.getId());
			}
		}
		
		Collection<LogicController> controllers=map.values();
		for(LogicController logicController:controllers) {
			logicController.getWebClient().sendMessage(message);
		}
	}


	public static void roomNodeUpdate(Room room) {
		if(room.getRoom_type()==RoomType.NOMAL_ROOM) {
			RoomNode roomNode=room.getRoomNode();
			roomNode.getSeats().clear();
			roomNode.setCur_player(room.getAllControllers().size());
			roomNode.getSeats().putAll(PckUtil.packageSeats(room));
			RoomNodeUtil roomNodeUtil=ZeroContext.getInstance(RoomNodeUtil.class);
			roomNodeUtil.insertOrUpdate(roomNode);		
		}
	}


	public static int getNextPosByUid(Room room, int uid) {
		Integer find=null;
		int pos=getPosByUid(room, uid);
		int max_player=room.getMax_player();
		Map<Integer, Integer> seats=room.getSeats();
		RoomCache roomCache = room.getRoomCache();
		Set<Integer> watchers=roomCache.getWatchers();
		Set<Integer> taotais=roomCache.getTaotais();
		for(int i=1;i<=max_player;i++) {
			int pos1 = (pos + i >max_player ? pos + i - max_player : pos + i);
			Integer next=seats.get(pos1);
			if(next!=null&&!watchers.contains(next)&&!taotais.contains(next)) {
				find=next;
				break;
			}
		}
		return find;
	}
	
	
	public static void main(String[] args) {
//		Map<Integer,Integer> seats=new HashMap<>();
//		for(int i=1;i<=10;i++) {
//			seats.put(i, null);
//		}
//		seats.put(2, 2);
//		seats.put(4, 4);
//		seats.put(5, 5);
//		seats.put(8, 8);
//		seats.put(10, 10);
//		int pos=7;
//		for(int i=1;i<=100;i++) {
//			pos=test(seats, pos);
//			System.out.print(pos+",");
//		}
	}
	public static Integer test(Map<Integer,Integer> seats,int pos) {
		Integer find=null;
		for(int i=1;i<=10;i++) {
			int pos1 = (pos + i >10 ? pos + i - 10 : pos + i);
			Integer next=seats.get(pos1);
			if(next!=null) {
				find=next;
				break;
			}
		}
		return find;
	}

	public static List<LogicController> birdPeopers(Room room) {
		List<LogicController> result=new ArrayList<LogicController>();
		Collection<LogicController> controllers=room.getAllControllers().values();
		RoomCache roomCache = room.getRoomCache();
		Map<Integer, Integer> birdmap=roomCache.getBirds();
		for(LogicController controller:controllers) {
			int uid=controller.getId();
			if(birdmap.containsKey(uid)) {
				result.add(controller);
			}
		}
		return result;
	}
	
	public static List<LogicController> readyPeopers(Room room) {
		List<LogicController> result=new ArrayList<LogicController>();
		Collection<LogicController> controllers=room.getAllControllers().values();
		GameBase gameBase=room.getGameBase();
		Map<Integer,Long> readys=gameBase.getReadys();
		for(LogicController controller:controllers) {
			int uid=controller.getId();
			if(readys.containsKey(uid)) {
				result.add(controller);
			}
		}
		return result;
	}
	
	public static List<LogicController> notReadyPeopers(Room room) {
		List<LogicController> result=new ArrayList<LogicController>();
		Collection<LogicController> controllers=room.getAllControllers().values();
		GameBase gameBase=room.getGameBase();
		Map<Integer,Long> readys=gameBase.getReadys();
		for(LogicController controller:controllers) {
			int uid=controller.getId();
			if(!readys.containsKey(uid)) {
				result.add(controller);
			}
		}
		return result;
	}


	public static int agreeDissolutionCount(DissolutionData dissolutionData) {
		int count=0;
		Map<Integer, Boolean> map=dissolutionData.getDissolutions();
		for(Entry<Integer,Boolean> entry:map.entrySet()) {
			if(entry.getValue()) {
				count++;
			}
		}
		return count;
	}


	public static void offlineRoomController(Room room, LogicController logicController) {
		RoomCache roomCache = room.getRoomCache();
		roomCache.getOfflines().add(logicController.getId());
		broadRoomAllControllersInclude(room, Message.build(LOGICCMD.NOTIFY_SOMEONE_OFFLINE, Resp.build(Code.OK, "某人离线",PckUtil.packageNotifySomeOneOffline(logicController.getId()))),logicController);
	}


	public static void someoneOnline(Room room, LogicController online) {
		RoomCache roomCache = room.getRoomCache();
		if(roomCache.getOfflines().contains(online.getId())) {
			roomCache.getOfflines().remove(online.getId());
		}
		broadRoomAllControllersInclude(room, Message.build(LOGICCMD.NOTIFY_SOMEONE_ONLINE, Resp.build(Code.OK, "某人重新上线",PckUtil.packageNotifySomeoneOnline(online.getId()))),online);		
	}


	public static void cancleAutoDeposit(Room room,LogicController controller) {
		int uid=controller.getId();
		GameBase gameBase = room.getGameBase();
		if(gameBase.getAuto_deposit().containsKey(uid)) {
			gameBase.getAuto_deposit().remove(uid);
			LogicUtil.broadRoomAllControllersInclude(room, Message.build(LOGICCMD.NOTIFY_EXIT_AUTODEPOSIT, Resp.build(Code.OK, "退出托管",PckUtil.packageNotifyExitAutoDeposit(uid,System.currentTimeMillis()))),controller);
		}			
	}


	public static void autoAnswerDissolution(Room room) {
		RoomCache roomCache = room.getRoomCache();
		DissolutionData dissolutionData = roomCache.getDissolutionData();
		long now=System.currentTimeMillis();
		if(!dissolutionData.getDissolutions().isEmpty()) {
			//有人发起解散了
			long dissolution_apply_time=dissolutionData.getDissolution_apply_time();
			int dissolution_total_time=dissolutionData.getDissolution_total_time();
			if(now-dissolution_apply_time>=dissolution_total_time*1000) {
				//自动为没有应答的玩家应答同意
				List<Integer> uids=new ArrayList<>();
				uids.addAll(room.getControllersWithoutWatcherAndTaotai().keySet());
				uids.removeAll(dissolutionData.getDissolutions().keySet());
				if(!uids.isEmpty()) {
					ILogicService logicService =ZeroContext.getInstance(ILogicService.class);
					for(Integer uid:uids) {
						LogicController logicController =room.getControllersWithoutWatcherAndTaotai().get(uid);
						logicService.reqDissolutionAnswer(room, logicController, 1);
					}
				}
			}
		}
	}


	public static boolean inDissolution(Room room) {
		boolean inDissolution=false;
		RoomCache roomCache = room.getRoomCache();
		DissolutionData dissolutionData = roomCache.getDissolutionData();
		if(!dissolutionData.getDissolutions().isEmpty()) {
			inDissolution=true;
		}
		return inDissolution;
	}



















}
